#include "base/backtrace.hpp"

#include <cxxabi.h>
#include <dlfcn.h>
#include <execinfo.h>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <unistd.h>

namespace ibox::base {

void dump_backtrace() {
    const int max_trace_depth = 16;
    void *trace_addresses[max_trace_depth];
    int trace_depth = backtrace(trace_addresses, max_trace_depth);
    char **trace_symbols = backtrace_symbols(trace_addresses, trace_depth);

    if (trace_symbols == nullptr) {
        std::cerr << "Failed to obtain backtrace symbols." << '\n';
        return;
    }

    for (int i = 0; i < trace_depth; i++) {
        char *symbol = trace_symbols[i];

        // Demangle function name if available
        Dl_info info;
        if (static_cast<bool>(dladdr(trace_addresses[i], &info))
            && info.dli_sname) {
            int status = -1;
            char *demangled_name = abi::__cxa_demangle(
                info.dli_sname, nullptr, nullptr, &status);
            if (status == 0 && demangled_name) {
                std::cout << "[" << i << "] " << demangled_name << '\n';
                free(demangled_name);
            } else {
                std::cout << "[" << i << "] " << info.dli_sname << '\n';
            }
        } else {
            std::cout << "[" << i << "] " << symbol << '\n';
        }
    }

    free(trace_symbols);
}

} // namespace ibox::base
